package com.itsome.util;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.event.AnalysisEventListener;
import com.itsome.pojo.FssExcelTypeEnum;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.List;

/**
 * <li>读取</li>
 * <li>默认从第一个sheet的第二行开始读, such as {@link #synchronousRead(MultipartFile, Class)}</li>
 * <li>指定sheet和行数, such as {@link #synchronousRead(MultipartFile, Class, int, int)}</li>
 * <li>读取全部sheet, such as {@link #repeatedRead(MultipartFile, Class, AnalysisEventListener)}</li>
 *
 * @author itsome on 2020-04-15
 */
@Slf4j
@UtilityClass
public class ExcelUtils {

    private static final String ROW = "row";

    /**
     * 默认从第一个sheet的第二行开始读
     */
    public static <T> List<T> synchronousRead(MultipartFile file, Class<T> clazz) throws IOException {
        List<T> list = EasyExcel.read(getInputStream(file)).head(clazz).sheet().doReadSync();
        setRow(list, clazz, 1);
        return list;
    }

    /**
     * 指定sheet和行数
     */
    public static <T> List<T> synchronousRead(MultipartFile file, Class<T> clazz, int sheetNo, int headLineNum) throws IOException {
        List<T> list = EasyExcel.read(getInputStream(file)).head(clazz).sheet(sheetNo).headRowNumber(headLineNum).doReadSync();
        setRow(list, clazz, headLineNum);
        return list;
    }

    /**
     * 读取全部sheet
     * 这里需要注意 listener的doAfterAllAnalysed 会在每个sheet读取完毕后调用一次。然后所有sheet都会往同一个listener里面写
     */
    public static <T> void repeatedRead(MultipartFile file, Class<T> clazz, AnalysisEventListener listener) throws IOException {
        EasyExcel.read(getInputStream(file), clazz, listener).doReadAll();
    }

    private static <T> void setRow(List<T> list, Class<T> clazz, int headLineNum) {
        try {
            Field declaredField = clazz.getDeclaredField(ROW);
            if (declaredField == null) {
                return;
            }
            for (T t : list) {
                Field rowField = t.getClass().getDeclaredField(ROW);
                rowField.setAccessible(true);
                Class<?> type = rowField.getType();
                if (type == Integer.class) {
                    rowField.set(t, ++headLineNum);
                } else if (type == String.class) {
                    rowField.set(t, ++headLineNum + "");
                }
            }
        } catch (NoSuchFieldException | IllegalAccessException e) {
            log.error("excel导入，设置row异常", e);
            throw new RuntimeException("设置row异常");
        }
    }

    private static InputStream getInputStream(MultipartFile file) throws IOException {
        String fileName = file.getOriginalFilename();
        if (fileName == null) {
            throw new RuntimeException("文件名称为空！");
        }
        String suffixName = fileName.toLowerCase();
        if (!FssExcelTypeEnum.checkExcelType(suffixName)) {
            throw new RuntimeException("文件格式错误！");
        }
        return file.getInputStream();
    }
}
